package com.top.web.hooker;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.BaseAdapter;
import android.widget.CompoundButton;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.hooker.settings.Setting;
import com.hooker.settings.SettingHelper;
import com.tool.hooker.library.R;
import com.top.web.hooker.common.HookerIntent;
import com.top.web.hooker.common.ViewManager;
import com.top.web.hooker.search.Filters;
import com.top.web.hooker.search.GroupAdapters;
import com.top.web.hooker.search.ISearch;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class AppSelectActivity extends AppCompatActivity {
    private ListAdapter _filterable;
    private boolean _isSet = false;
    private BaseAdapter _listAdapter;
    public static final String FROM = "from";
    public static final String PACKAGE = "package";
    private String from;
    private String pgName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_apps);

        if (getIntent() != null) {
            from = getIntent().getStringExtra(FROM);

            if (HookerIntent.FROM_INJECT.equals(from)) {
                pgName = getIntent().getStringExtra(PACKAGE);
            }
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                final List<AppInfo> list = getAppList();

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        onReady(list);
                    }
                });
            }
        }).start();
    }

    private void onReady(final List<AppInfo> list) {
        final ListView listView = findViewById(R.id.list);
        final ListView searchList = findViewById(R.id.searchList);
        final AutoCompleteTextView searchView = findViewById(R.id.search);

        final Set<String> apps = new HashSet<>();
        if (HookerIntent.FROM_INJECT.equals(from) && pgName != null) {
            apps.addAll(SettingHelper.getInjectValues(getApplicationContext(), pgName));
        } else {
            apps.addAll(Setting.getHookApps(this));
        }

        Collections.sort(list, new Comparator<AppInfo>() {
            @Override
            public int compare(AppInfo o1, AppInfo o2) {
                if (apps.contains(o1.getPackageName()) && !apps.contains(o2.getPackageName())) {
                    return -1;
                } else if (apps.contains(o2.getPackageName()) && !apps.contains(o1.getPackageName())) {
                    return 1;
                }
                return 0;
            }
        });

        _filterable = getAdapter(list, apps);

        listView.setAdapter(new BaseAdapter() {
            @Override
            public int getCount() {
                return list.size();
            }

            @Override
            public Object getItem(int position) {
                return list.get(position);
            }

            @Override
            public long getItemId(int position) {
                return position;
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                if (convertView == null) {
                    convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.app_item, null);
                    convertView.setTag(ViewManager.getManager(convertView));
                }

                ViewManager viewManager = (ViewManager) convertView.getTag();

                final PackageInfo item = ((AppInfo) getItem(position)).info();
                Drawable drawable = item.applicationInfo.loadIcon(getPackageManager());

                CharSequence name = item.applicationInfo.loadLabel(getPackageManager());

                viewManager.setImageSource(R.id.icon, drawable);
                viewManager.setText(R.id.title, name.toString());
                Switch s = viewManager.find(R.id.toggle);
                s.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        handleOnChecked(apps, isChecked, item.packageName);
                    }
                });

                if (apps.contains(item.packageName)) {
                    s.setChecked(true);
                } else {
                    s.setChecked(false);
                }

                return convertView;
            }
        });

        searchView.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if ("".equals(s.toString()) || _isSet) {
                    _isSet = false;
                    getFilter().filter("\1");
                    listView.setVisibility(View.VISIBLE);
                    searchList.setVisibility(View.GONE);
                    return;
                }

                getFilter().filter(s.toString(), new Filter.FilterListener() {
                    @Override
                    public synchronized void onFilterComplete(int count) {
                        if ("".equals(searchView.getText().toString())) {
                            listView.setVisibility(View.VISIBLE);
                            searchList.setVisibility(View.GONE);
                        } else {
                            listView.setVisibility(View.GONE);
                            searchList.setVisibility(View.VISIBLE);
                        }

                        searchList.setAdapter(_filterable);
                    }
                });
            }
        });
    }


    private void handleOnChecked(Set<String> apps, boolean isChecked, String packageName) {
        if (isChecked) {
            apps.add(packageName);
        } else {
            apps.remove(packageName);
        }

        if (HookerIntent.FROM_HOOKER.equals(from)) {
            if (isChecked) {
                Setting.hook(getApplicationContext(), packageName);
            } else {
                Setting.unHook(getApplicationContext(), packageName);
            }

        } else if (HookerIntent.FROM_INJECT.equals(from) && pgName != null) {
            SettingHelper.inject(getApplicationContext(), pgName, apps.toArray(new String[apps.size()]));
        }
    }

    public class AppInfo implements Filters.KeyProvider {
        private PackageInfo _info;
        private String _name;

        public AppInfo(PackageInfo info) {
            _info = info;
            _name = _info.applicationInfo.loadLabel(getPackageManager()) + "";
        }

        public PackageInfo info() {
            return _info;
        }

        public String getPackageName() {
            if (_info != null) {
                return _info.packageName;
            }
            return "";
        }

        @Override
        public String[] getKeys() {
            return new String[]{_name};
        }
    }

    private ListAdapter getAdapter(final List<AppInfo> list, final Set<String> apps) {
        final Context context = getApplicationContext();

        return _listAdapter = new GroupAdapters.FilterListGroupAdapter<String, AppInfo>(new ISearch<String, AppInfo>() {
            @Override
            public String getName() {
                return "app";
            }

            @Override
            public Cancelable search(CharSequence key, SearchListener<AppInfo> listener) {
                for (AppInfo info : list) {
                    listener.onFind(info);
                }

                listener.onCompleted();

                return new Cancelable() {
                    @Override
                    public void cancel() {

                    }
                };
            }

            @Override
            public <T> T param(String name, T def) {
                return null;
            }

            @Override
            public void put(String name, Object value) {

            }
        }) {
            @Override
            public View getHeaderView(final int group, View headerView) {
                return new View(getApplicationContext());
            }

            @Override
            public int getGroupItemMax(int group) {
                return Integer.MAX_VALUE;
            }

            @Override
            public int getItemCount() {
                int sum = 0;
                for (int i = 0; i < getGroupList().size(); i++) {
                    sum += getGroupItemCount(i);
                }

                return sum;
            }

            @Override
            public View getGroupItemView(final int group, int i, View convertView, ViewGroup groupView) {
                if (i == getGroupItemMax(group) - 1) {
                    TextView textView = new TextView(context);
                    textView.setText("更多");
                    textView.setGravity(Gravity.CENTER);
                    return textView;
                } else {
                    if (convertView == null) {
                        convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.app_item, null);
                        convertView.setTag(ViewManager.getManager(convertView));
                    }

                    ViewManager viewManager = (ViewManager) convertView.getTag();

                    final PackageInfo item = getGroupList().get(getGroupList().getKey(group)).get(i).info();
                    Drawable drawable = item.applicationInfo.loadIcon(getPackageManager());

                    CharSequence name = item.applicationInfo.loadLabel(getPackageManager());

                    viewManager.setImageSource(R.id.icon, drawable);
                    viewManager.setText(R.id.title, name.toString());
                    Switch s = viewManager.find(R.id.toggle);
                    s.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                            handleOnChecked(apps, isChecked, item.packageName);
                        }
                    });

                    if (apps.contains(item.packageName)) {
                        s.setChecked(true);
                    } else {
                        s.setChecked(false);
                    }

                    return convertView;
                }
            }
        };
    }

    private List<AppInfo> getAppList() {
        List<AppInfo> apps = new ArrayList<>();
        for (PackageInfo info : getPackageManager().getInstalledPackages(0)) {
            apps.add(new AppInfo(info));
        }

        return apps;
    }

    private Filter getFilter() {
        if (_filterable instanceof Filterable) {
            return ((Filterable) _filterable).getFilter();
        }

        return new Filter() {
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                return new FilterResults();
            }
        };
    }
}
